\ SEE - a Forth decompiler for TurboForth V1.1 by Mark Wills
NEW
        0 VALUE addr           
    $8320 CONSTANT 'DOCOL
    $832C CONSTANT 'EXIT            
   CHAR " CONSTANT ""  
        0 VALUE saddr

: addr+2   ( --) 2 +TO addr ; \ point to next word (16 bit)

: .addr| CR addr $. ." | " ;

\ if the word name won't fit on the current line then new line
: wrap ( word_len -- word_len)
  DUP XY? DROP + XMAX >= IF .addr| THEN ;

\ display the name of the word
: .name ( cfa --) 
  >LINK ?DUP IF 2+ DUP @ 15 AND SWAP 2+ SWAP wrap 
  TYPE SPACE ELSE ." ?  " THEN ;

: .lit ( --) 
  addr+2 addr @ N>S 1+ wrap 1- type space ; \ display a literal value

: .addr ( --) 
  .lit ; \ display an address
  
: .TOname ( --)
    addr+2 addr @ 2- .name ;

\ display a string, adjust address pointer accordingly
: .str ( --) 
  addr+2 addr DUP C@ DUP ." $" $. SWAP 1+ SWAP "" EMIT TYPE 
  "" EMIT  addr C@ +TO addr addr 2+ $FFFE AND TO addr ;

: a-2 ( --) -2 +TO addr ;

\ process special cases eg. literals, addresses etc
: decode ( --)   addr @ CASE
    ['] LIT     OF .name .lit  ENDOF
    ['] BRANCH  OF .name .addr ENDOF
    ['] 0BRANCH OF .name .addr ENDOF
    ['] (S")    OF .addr| .name .str .addr| a-2 ENDOF
    ['] (DO)    OF .name .addr ENDOF
    ['] (LOOP)  OF .name .addr ENDOF
    ['] (+LOOP) OF .name .addr ENDOF
    ['] (TO)    OF .name .TOname ENDOF
    ['] (+TO)   OF .name .TOname ENDOF
    .name ( else case)
  ENDCASE ;

: SEE ( "word" --) 
  base @ >r hex
  CR ' DUP TO addr  DUP >LINK TO saddr
  IF CR
    \ word is in the dictionary
    addr @ 'DOCOL = IF
        \ word is a colon definition...
        \ check if the word is immediate...
        saddr 2+ @ $8000 AND IF ." *IMMEDIATE* " CR THEN
        \ report dictionary and code start addresses...
        ." Starts:$" saddr $. ."  Code starts:$" addr $.
        \ show name of word (e.g. : FRED)...
        CR  ." : " addr .name addr+2
        \ run in a loop until we hit the EXIT opcode...
        .addr| 
        BEGIN addr @ 'EXIT <> WHILE
            \ opcode is not EXIT, so look it up and display it
            addr @ decode  addr+2
            BEGIN KEY? -1 = UNTIL
        REPEAT  cr addr $. ." ;"
        \ report the size of the word...
        decimal addr+2 CR ." Size:" addr saddr - . ." bytes"
    ELSE
        ." Assembly language word or data @ $" addr $.
    THEN
  ELSE
    ." not found"
  THEN CR
  r> base !
;

